//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.quickserver.util.pool.thread;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.quickserver.net.server.ClientEvent;
import org.quickserver.net.server.ClientHandler;
import org.quickserver.util.MyString;

public class ClientThread extends Thread {
    private static final Logger logger = Logger.getLogger(ClientThread.class.getName());
    private static Map idMap = new HashMap();
    private String name;
    private final ClientPool pool;
    private Runnable client;
    private int id;
    private boolean ready;
    protected volatile char state;

    public boolean isReady() {
        return this.ready;
    }

    public void clean() {
        this.client = null;
    }

    public ClientThread(ClientPool pool) {
        this(pool, -1);
    }

    private static int getNewId(int instanceCount) {
        ClientThread.InstanceId instanceId = (ClientThread.InstanceId)idMap.get("" + instanceCount);
        if (instanceId == null) {
            instanceId = new ClientThread.InstanceId();
            idMap.put("" + instanceCount, instanceId);
        }

        return instanceId.getNextId();
    }

    public ClientThread(ClientPool pool, int instanceCount) {
        this.name = "<ClientThread-Pool#";
        this.ready = false;
        this.state = 'U';
        this.id = getNewId(instanceCount);
        this.name = this.name + instanceCount + "-ID:" + this.id + ">";
        this.pool = pool;
        this.setName(this.name);
    }

    public int getInstanceId() {
        return this.id;
    }

    private void executeClient() {
        boolean niowriteFlag = false;
        this.state = 'R';
        if (ClientHandler.class.isInstance(this.client)) {
            niowriteFlag = ((ClientHandler)this.client).isClientEventNext(ClientEvent.WRITE);
            if (niowriteFlag) {
                this.pool.nioWriteStart();
            }
        } else {
            niowriteFlag = false;
        }

        try {
            this.client.run();
        } catch (RuntimeException var6) {
            logger.warning("RuntimeException @ thread run() : " + this.getName() + ": " + MyString.getStackTrace(var6));
        } finally {
            if (niowriteFlag) {
                this.pool.nioWriteEnd();
            }

        }

        this.state = 'I';
    }

    public void run() {
        this.state = 'S';
        if (this.pool.isClientAvailable()) {
            this.ready = true;
            ClientPool var1 = this.pool;
            synchronized(this.pool) {
                this.pool.notify();
            }
        }

        boolean returnToPool = false;

        while(true) {
            if (this.ready) {
                this.state = 'L';
                this.client = this.pool.getClient();
                if (this.client == null) {
                    logger.fine("ClientPool returned a null client! Other Thread must have taken my client.. Ok");
                } else {
                    this.executeClient();
                    logger.log(Level.FINEST, "Client returned the thread: {0}", this.getName());
                    this.client = null;
                    if (this.pool == null) {
                        logger.log(Level.FINE, "Could not returning client thread {0}, pool was null!", this.getName());
                        this.state = 'D';
                        break;
                    }
                }

                if (this.pool.isClientAvailable()) {
                    this.state = 'L';
                    continue;
                }

                returnToPool = true;
            }

            synchronized(this) {
                if (!this.ready) {
                    this.ready = true;
                }

                if (returnToPool) {
                    logger.log(Level.FINEST, "Returning client thread to pool: {0}", this.getName());
                    this.pool.returnObject(this);
                    returnToPool = false;
                    this.state = 'P';
                }

                try {
                    this.state = 'W';
                    this.wait();
                    this.state = 'N';
                } catch (InterruptedException var5) {
                    logger.log(Level.FINEST, "Closing thread {0} since interrupted.", Thread.currentThread().getName());
                    this.state = 'D';
                    break;
                }
            }
        }

    }

    public Runnable getThread() {
        return this.client;
    }

    public String toString() {
        return super.toString() + " - " + this.state + " - Client " + this.client;
    }

    static class InstanceId {
        private int id = 0;

        InstanceId() {
        }

        public int getNextId() {
            return ++this.id;
        }
    }
}
